home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 1 / BBS in a box - Trilogy I.iso / Files / MIDI / H-M / midifile routines Folder / writemidi.c < prev   
Encoding:
C/C++ Source or Header  |  1992-11-15  |  6.5 KB  |  308 lines  |  [TEXT/MPS ]

  1. /*  this program reads a csound score and writes a midi file.
  2.     The Csound instr. # become midi chan #, the start time and duration
  3.     should be in seconds, p4 should = midi amp i.e.between 0 and 127 and p5
  4.     should be the midi note number 0 to 127. */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8.  
  9. FILE    *fp;
  10.  
  11. WriteVarLen(value)
  12.     long value;
  13. {
  14.     long    buffer;
  15.     buffer    = value & 0x7f;
  16.     while((value>>=7) > 0)
  17.     {
  18.         buffer    <<= 8;
  19.         buffer    |= 0x80;
  20.         buffer    += (value & 0x7f);
  21.     }
  22.     while(1)
  23.     {
  24.         putc((int) (buffer & 0xFF),fp);
  25.         if(buffer & 0x80)
  26.              buffer    >>= 8;
  27.         else
  28.             break;
  29.     }
  30. }
  31. int CountWriteVarLen(value)
  32.     long value;
  33. {
  34.     long    buffer;
  35.     int        count;
  36.     count = 0;
  37.     buffer    = value & 0x7f;
  38.     while((value>>=7) > 0)
  39.     {
  40.         buffer    <<= 8;
  41.         buffer    |= 0x80;
  42.         buffer    += (value & 0x7f);
  43.     }
  44.     while(1)
  45.     {
  46.         count++;
  47.         if(buffer & 0x80)
  48.              buffer    >>= 8;
  49.         else
  50.             break;
  51.     }
  52.     return count;
  53. }
  54.  
  55.  
  56.  
  57. float    *setimes;
  58. unsigned short   *voice,*notenum,*amp;
  59. float    tempf;
  60. unsigned short    tempb;
  61. int    i;
  62. /* recursive sort algorithm. see p.87 "The C Programming Language" */
  63. /*  by Kerningham and Ritchie */
  64. QuickSort(left,right)
  65.     int left,right;
  66. {
  67.     int    last;
  68.     if(left>=right)
  69.         return;
  70.     tempf = setimes[left] ;
  71.     setimes[left] = setimes[(left+right)/2] ;
  72.     setimes[(left+right)/2] = tempf ;
  73.  
  74.     tempb = voice[left] ;
  75.     voice[left] = voice[(left+right)/2] ;
  76.     voice[(left+right)/2] = tempb ;
  77.  
  78.     tempb = notenum[left] ;
  79.     notenum[left] = notenum[(left+right)/2] ;
  80.     notenum[(left+right)/2] = tempb ;
  81.  
  82.     tempb = amp[left] ;
  83.     amp[left] = amp[(left+right)/2] ;
  84.     amp[(left+right)/2] = tempb ;
  85.     
  86.     last = left;
  87.     for(i=left+1; i<=right ; i++)
  88.         if(setimes[i] < setimes[left])
  89.             if(i != (++last))
  90.             {
  91.                 tempf = setimes[i] ;
  92.                 setimes[i] = setimes[last] ;
  93.                 setimes[last] = tempf ;
  94.  
  95.                 tempb = voice[i] ;
  96.                 voice[i] = voice[last] ;
  97.                 voice[last] = tempb ;
  98.  
  99.                 tempb = notenum[i] ;
  100.                 notenum[i] = notenum[last] ;
  101.                 notenum[last] = tempb ;
  102.  
  103.                 tempb = amp[i] ;
  104.                 amp[i] = amp[last] ;
  105.                 amp[last] = tempb ;
  106.             }
  107.     
  108.     tempf = setimes[left] ;
  109.     setimes[left] = setimes[last] ;
  110.     setimes[last] = tempf ;
  111.  
  112.     tempb = voice[left] ;
  113.     voice[left] = voice[last] ;
  114.     voice[last] = tempb ;
  115.  
  116.     tempb = notenum[left] ;
  117.     notenum[left] = notenum[last] ;
  118.     notenum[last] = tempb ;
  119.  
  120.     tempb = amp[left] ;
  121.     amp[left] = amp[last] ;
  122.     amp[last] = tempb ;
  123.     QuickSort(left,last-1);
  124.     QuickSort(last+1,right);
  125. }
  126.  
  127. main(argc,argv)
  128.     int argc;
  129.     char    *argv[];
  130. {
  131.     char    ch;
  132.     float    p1,p2,p3,p4,p5;
  133.     unsigned short    tempb;
  134.     int        noteCount=0,i,j;
  135.     long    byteCount;
  136.     long    totalticks,templ;
  137.     long    tempo = 1000000;    /* tempo in micro seconds per quarter note */
  138.     long    arraysize;
  139.  
  140.     arraysize = 3500;
  141.     if(argc==4)
  142.         sscanf(argv[3],"%d",&arraysize);
  143.     if(argc!=3 && argc!=4)
  144.     {
  145.         printf("Usage: %s csound.sco midifile.fil [maxeventcount]\n",argv[0]);
  146.         exit(-1);
  147.     }
  148.     printf("This program will read the C Sound format file named %s, and\n",argv[1]);
  149.     printf("then write it in Midi file format to the file %s.\n\n\n",argv[2]);
  150.     
  151. /* allocate storage arrays */
  152.     setimes = (float *) calloc(arraysize,sizeof(float));
  153.     voice = (unsigned short *) calloc(arraysize,sizeof(unsigned short));
  154.     notenum = (unsigned short *) calloc(arraysize,sizeof(unsigned short));
  155.     amp = (unsigned short *) calloc(arraysize,sizeof(unsigned short));
  156.     if(setimes==NULL||voice==NULL||notenum==NULL||amp==NULL)
  157.     {
  158.         printf("Enough storage could not be allocated to run this program.\n");
  159.         exit(-1);
  160.     }
  161.  
  162.     fp = fopen(argv[1],"r");
  163.     if(fp == NULL)
  164.     {
  165.         printf(" Error : The file %s could not be opened !\n",argv[1]);
  166.         exit(-1);
  167.     }
  168.  
  169.  
  170. /* read in the Cscore */
  171.     printf(" Reading in the C Sound score. i cards only.\n");
  172.     while(fscanf(fp,"%c",&ch)!=EOF)
  173.     {
  174.         if(ch==';')
  175.             while(fscanf(fp,"%c",&ch)!=EOF && ch!='\n')
  176.                 {}
  177.         else if(ch=='i'||ch=='I')
  178.         {
  179.             fscanf(fp,"%f %f %f %f %f",&p1,&p2,&p3,&p4,&p5);
  180.              setimes[noteCount] = p2;
  181.              voice[noteCount] = p1;
  182.              notenum[noteCount] = p5;
  183.              amp[noteCount] = p4;
  184.             noteCount++ ;
  185.              setimes[noteCount] = p3+p2;
  186.              voice[noteCount] = 100+p1;
  187.              notenum[noteCount] = p5;
  188.              amp[noteCount] = 0;
  189.             noteCount++ ;
  190.             if(noteCount>arraysize-2)
  191.              {
  192.               printf(" Error : too many notes so, not all of the notes could be processed !\n");
  193.               break;
  194.             }
  195.         }
  196.     }
  197.     fclose(fp);
  198.     printf(" A total of %d events were read.\n",noteCount);
  199.  
  200. /* sort the score by setimes */
  201.     printf("\n Sorting the Csound score.\n");
  202. /* recursive sort */
  203.     QuickSort(0,noteCount-1);
  204. /* bubble sort */
  205. /*    for(i=0;i<noteCount;i++)
  206.     {
  207.     printf("\n Sorting the Csound score.\n");
  208.       for(j=1;j<noteCount;j++)
  209.         if(setimes[j-1]>setimes[j])
  210.         {
  211.         tempf = setimes[j-1] ;
  212.         setimes[j-1] = setimes[j] ;
  213.         setimes[j] = tempf ;
  214.  
  215.         tempb = voice[j-1] ;
  216.         voice[j-1] = voice[j] ;
  217.         voice[j] = tempb ;
  218.  
  219.         tempb = notenum[j-1] ;
  220.         notenum[j-1] = notenum[j] ;
  221.         notenum[j] = tempb ;
  222.  
  223.         tempb = amp[j-1] ;
  224.         amp[j-1] = amp[j] ;
  225.         amp[j] = tempb ;
  226.         }
  227.     }
  228. */
  229. /* print the score */
  230.     fp = fopen(argv[2],"w");
  231.     if(fp == NULL)
  232.     {
  233.         printf("\n Error : The file %s could not be opened !\n",argv[2]);
  234.         exit(-1);
  235.     }
  236.     
  237.     printf("\n writing the Midi file.\n");
  238.     putc('M',fp);    /* put 'MThd' header */
  239.     putc('T',fp);
  240.     putc('h',fp);
  241.     putc('d',fp);
  242.     putc(0,fp);        /* put length */
  243.     putc(0,fp);
  244.     putc(0,fp);
  245.     putc(6,fp);
  246.     putc(0,fp);        /* format 0 */
  247.     putc(0,fp);
  248.     putc(0,fp);        /* one track */
  249.     putc(1,fp);
  250.     putc(1,fp);        /* 480 ticks per quarter */
  251.     putc(0xE0,fp);
  252.     putc('M',fp);    /* put 'MTrk' header */
  253.     putc('T',fp);
  254.     putc('r',fp);
  255.     putc('k',fp);
  256.     
  257.     printf(" calculating track length = ");
  258.     /* calc track length */
  259.     byteCount = 0;
  260.     totalticks = 0;
  261.     for(i=0;i<noteCount;i++)
  262.     {
  263.         templ = (double) setimes[i] * 480. ;
  264.         byteCount += CountWriteVarLen(templ-totalticks);
  265.         totalticks = templ;
  266.         byteCount+=3;
  267.     }
  268.     byteCount+=4;    /* for end of track mark */
  269.     printf("%ld bytes\n",byteCount);
  270.     
  271.     putc((int)(byteCount>>24),fp);        /* put length of track */
  272.     putc((int)(byteCount>>16),fp);
  273.     putc((int)(byteCount>>8),fp);
  274.     putc((int)(byteCount),fp);
  275.  
  276.     /* calc and put track */
  277.     printf(" writing track data.\n");
  278.     totalticks = 0;
  279.     for(i=0;i<noteCount;i++)
  280.     {
  281.         templ = (double) setimes[i] * 480. ;
  282.         WriteVarLen(templ-totalticks);
  283.         if(voice[i]<101) putc((int)0x90+((voice[i]-1) & 0x0F),fp); /*note no/off */
  284.         else             putc((int)0x80+((voice[i]-101) & 0x0F),fp);
  285.         putc((int)notenum[i],fp);                                /* note number */
  286.         putc((int)amp[i],fp);                                    /* velocity */
  287.  
  288.         totalticks = templ;
  289.     }
  290.  
  291.     putc(0,fp);        /* put end of track */
  292.     putc(0xFF,fp);
  293.     putc(0x2F,fp);
  294.     putc(0,fp);
  295.  
  296.     fclose(fp);
  297.     free(setimes);
  298.     free(voice);
  299.     free(notenum);
  300.     free(amp);
  301.  
  302.     printf(" done.\n");
  303.  
  304. }
  305.  
  306.  
  307.  
  308.